var SubPub = Class.create({
			initialize : function() {
				this.currentRandomeString = MD5('');
				this.stubMap = {};
				this.channels = {};
			},
			subscribe : function(hash, cb, scope) {
				if (typeof(hash) == 'string' && cb) {
					scope = scope || this;
					return this.subscribe({
								name : hash,
								callback : cb,
								scope : scope
							});
				}
				if (!hash)
					throw 'must call with a hash parameter';
				if (!hash.name && !hash.channel)
					throw 'must call with name parameter in hash';
				hash.name = hash.name || hash.channel;
				if (typeof(hash.name) != 'string')
					throw 'name parameter must be string';
				if (!hash.callback && !hash.closure && !hash.handler)
					throw 'must call with callback';
				if (!this.channels[hash.name])
					this.channels[hash.name] = {};
				var stub = randomString();
				var callbackStub = {
					name : hash.name,
					callback : hash.callback || hash.closure || hash.handler,
					scope : hash.scope
				};
				this.channels[hash.name][stub] = callbackStub;
				this.stubMap[stub] = callbackStub;
				return stub;
			},
			unsubscribe : function(stub) {
				delete this.channels[this.stubMap[stub].name][stub];
			},
			publish : function(hash, args) {
				if (typeof(hash) == 'string') {
					return this.publish({
								name : hash,
								args : (args instanceof Array ? args : (args
										? [args]
										: []))
							});
				}
				if (!hash)
					throw 'must call with a hash parameter';
				if (!hash.name && !hash.channel)
					throw 'must call with name parameter in hash';
				hash.name = hash.name || hash.channel;
				if (typeof(hash.name) != 'string')
					throw 'name parameter must be string';
				if (this.channels[hash.name]) {
					for (var stub in this.channels[hash.name]) {
						var cb = this.channels[hash.name][stub];
						try {
							cb.callback.apply(cb.scope || this, hash.args
											|| hash.arguments || []);
						} catch (e) {
							console.log('Error in publishing ' + hash.name);
							console.dir(e.stack || e);
						}
					}
				}
			}
		});
